//
//  LZChangeProject.m
//  LZSpamCode
//
//  Created by ZengLiZhi on 2024/6/26.
//

#import "LZChangeProject.h"
#import "LZSpamCodeManager.h"
#import "LZFileManager.h"
#import "LZChangeClassName.h"

@implementation LZChangeProject

+ (void)start{
    
    NSString *gOldProjectName = [LZSpamCodeManager shareInstance].gOldProjectName;
    NSString *gNewProjectName = [LZSpamCodeManager shareInstance].gNewProjectName;
    NSString *gProjectPath = [LZSpamCodeManager shareInstance].gProjectPath;
    
    if (gOldProjectName && gNewProjectName) {
        //修改.sh文件
        NSString *shPath = [NSString stringWithFormat:@"%@/b.sh",gProjectPath];
        NSError *error = nil;
        NSMutableString *shContent = [NSMutableString stringWithContentsOfFile:shPath encoding:NSUTF8StringEncoding error:&error];
        if (error) {
            printf("打开b.sh文件 %s 失败：%s\n", shPath.UTF8String, error.localizedDescription.UTF8String);
        }else{
            NSString *regularExpression = [NSString stringWithFormat:@"\\b%@\\b", gOldProjectName];
            BOOL isChanged = [LZFileManager regularReplacement:shContent regularExpression:regularExpression newString:gNewProjectName];
            if (!isChanged) {
                printf("修改.sh文件 失败 \n");
            }else{
                printf("修改.sh文件 完成 \n");
            }
            [shContent writeToFile:shPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
        }
        
        @autoreleasepool {
            //修改工程名
            NSString *dir = [LZSpamCodeManager shareInstance].gSourceCodeDir.stringByDeletingLastPathComponent;
            [LZChangeProject modifyProjectName:dir oldName:gOldProjectName newName:gNewProjectName];
        }
        
        printf("修改工程名完成: %s => %s \n",gOldProjectName.UTF8String,gNewProjectName.UTF8String);
        [LZSpamCodeManager shareInstance].gSourceCodeDir = [NSString stringWithFormat:@"%@/%@",gProjectPath,gNewProjectName];
    }
}

+(void)modifyProjectName:(NSString *)projectDir
                 oldName:(NSString *)oldName
                 newName:(NSString *)newName {
    NSString *sourceCodeDirPath = [projectDir stringByAppendingPathComponent:oldName];
    NSString *xcodeprojFilePath = [sourceCodeDirPath stringByAppendingPathExtension:@"xcodeproj"];
    NSString *xcworkspaceFilePath = [sourceCodeDirPath stringByAppendingPathExtension:@"xcworkspace"];
    
    NSFileManager *fm = [NSFileManager defaultManager];
    BOOL isDirectory;
    
    // old-Swift.h > new-Swift.h
    [LZChangeClassName modifyFilesClassName:projectDir
                               oldClassName:[oldName stringByAppendingString:@"-Swift.h"]
                               newClassName:[newName stringByAppendingString:@"-Swift.h"]];
    //old.pch => new.pch
    NSString *pchPath = [LZFileManager findFilePath:[projectDir stringByAppendingPathComponent:oldName]
                            targetFileName:[NSString stringWithFormat:@"%@.pch",oldName]];
    NSString *newPchPath = [pchPath stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@.pch",oldName] withString:[NSString stringWithFormat:@"%@.pch",newName]];
    if (pchPath.length) {
        [LZFileManager renameFile:pchPath newPath:newPchPath];
    }
    
    // 改 Podfile 中的工程名
    NSString *podfilePath = [projectDir stringByAppendingPathComponent:@"Podfile"];
    if ([fm fileExistsAtPath:podfilePath isDirectory:&isDirectory] && !isDirectory) {
        [self replacePodfileContent:podfilePath oldString:oldName newString:newName];
    }
    
    // 改工程文件内容
    if ([fm fileExistsAtPath:xcodeprojFilePath isDirectory:&isDirectory] && isDirectory) {
        // 替换 project.pbxproj 文件内容
        NSString *projectPbxprojFilePath = [xcodeprojFilePath stringByAppendingPathComponent:@"project.pbxproj"];
        if ([fm fileExistsAtPath:projectPbxprojFilePath]) {
            
            [self resetBridgingHeaderFileName:projectPbxprojFilePath
                                      oldName:[oldName stringByAppendingString:@"-Bridging-Header"]
                                      newName:[newName stringByAppendingString:@"-Bridging-Header"]];
            
            [self resetEntitlementsFileName:projectPbxprojFilePath oldName:oldName newName:newName];
            
            [self replaceProjectFileContent:projectPbxprojFilePath oldString:oldName newString:newName];
        }
        // 替换 project.xcworkspace/contents.xcworkspacedata 文件内容
        NSString *contentsXcworkspacedataFilePath = [xcodeprojFilePath stringByAppendingPathComponent:@"project.xcworkspace/contents.xcworkspacedata"];
        if ([fm fileExistsAtPath:contentsXcworkspacedataFilePath]) {
            [self replaceProjectFileContent:contentsXcworkspacedataFilePath oldString:oldName newString:newName];
        }
        // xcuserdata 本地用户文件
        NSString *xcuserdataFilePath = [xcodeprojFilePath stringByAppendingPathComponent:@"xcuserdata"];
        if ([fm fileExistsAtPath:xcuserdataFilePath]) {
            [fm removeItemAtPath:xcuserdataFilePath error:nil];
        }
        // 改名工程文件
        [LZFileManager renameFile:xcodeprojFilePath newPath:[[projectDir stringByAppendingPathComponent:newName] stringByAppendingPathExtension:@"xcodeproj"]];
    }
    
    // 改工程组文件内容
    if ([fm fileExistsAtPath:xcworkspaceFilePath isDirectory:&isDirectory] && isDirectory) {
        // 替换 contents.xcworkspacedata 文件内容
        NSString *contentsXcworkspacedataFilePath = [xcworkspaceFilePath stringByAppendingPathComponent:@"contents.xcworkspacedata"];
        if ([fm fileExistsAtPath:contentsXcworkspacedataFilePath]) {
            [self replaceProjectFileContent:contentsXcworkspacedataFilePath oldString:oldName newString:newName];
        }
        // xcuserdata 本地用户文件
        NSString *xcuserdataFilePath = [xcworkspaceFilePath stringByAppendingPathComponent:@"xcuserdata"];
        if ([fm fileExistsAtPath:xcuserdataFilePath]) {
            [fm removeItemAtPath:xcuserdataFilePath error:nil];
        }
        // 改名工程文件
        [LZFileManager renameFile:xcworkspaceFilePath newPath:[[projectDir stringByAppendingPathComponent:newName] stringByAppendingPathExtension:@"xcworkspace"]];
    }
    
    // 改源代码文件夹名称
    if ([fm fileExistsAtPath:sourceCodeDirPath isDirectory:&isDirectory] && isDirectory) {
        [LZFileManager renameFile:sourceCodeDirPath newPath:[projectDir stringByAppendingPathComponent:newName]];
    }
}

#pragma mark - 修改工程名
+(void)resetEntitlementsFileName:(NSString *)projectPbxprojFilePath oldName:(NSString *)oldName newName:(NSString *)newName {
    
    NSString *rootPath = projectPbxprojFilePath.stringByDeletingLastPathComponent.stringByDeletingLastPathComponent;
    
    NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:projectPbxprojFilePath encoding:NSUTF8StringEncoding error:nil];
    
    NSString *regularExpression = @"CODE_SIGN_ENTITLEMENTS = \"?([^\";]+)";
    
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        NSString *entitlementsPath = [fileContent substringWithRange:[obj rangeAtIndex:1]];
        NSString *entitlementsName = entitlementsPath.lastPathComponent.stringByDeletingPathExtension;
        
        if (![entitlementsName isEqualToString:oldName]) return;
        
        entitlementsPath = [rootPath stringByAppendingPathComponent:entitlementsPath];
        
        if (![[NSFileManager defaultManager] fileExistsAtPath:entitlementsPath]) return;
        
        NSString *newPath = [entitlementsPath.stringByDeletingLastPathComponent stringByAppendingPathComponent:[newName stringByAppendingPathExtension:@"entitlements"]];

        [LZFileManager renameFile:entitlementsPath newPath:newPath];
    }];
}

#pragma mark - 修改BridgingHeader
+(void)resetBridgingHeaderFileName:(NSString *)projectPbxprojFilePath oldName:(NSString *)oldName newName:(NSString *)newName {
    NSString *rootPath = projectPbxprojFilePath.stringByDeletingLastPathComponent.stringByDeletingLastPathComponent;
    NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:projectPbxprojFilePath encoding:NSUTF8StringEncoding error:nil];
    
    NSString *regularExpression = @"SWIFT_OBJC_BRIDGING_HEADER = \"?([^\";]+)";
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSString *entitlementsPath = [fileContent substringWithRange:[obj rangeAtIndex:1]];
        NSString *entitlementsName = entitlementsPath.lastPathComponent.stringByDeletingPathExtension;
        if (![entitlementsName isEqualToString:oldName]) return;
        entitlementsPath = [rootPath stringByAppendingPathComponent:entitlementsPath];
        if (![[NSFileManager defaultManager] fileExistsAtPath:entitlementsPath]) return;
        NSString *newPath = [entitlementsPath.stringByDeletingLastPathComponent stringByAppendingPathComponent:[newName stringByAppendingPathExtension:@"h"]];

        [LZFileManager renameFile:entitlementsPath newPath:newPath];
    }];
}

#pragma mark - Podfile
+(void)replacePodfileContent:(NSString *)filePath oldString:(NSString *)oldString newString:(NSString *)newString {
    NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    
    NSString *regularExpression = [NSString stringWithFormat:@"target +'%@", oldString];
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [fileContent replaceCharactersInRange:obj.range withString:[NSString stringWithFormat:@"target '%@", newString]];
    }];
    
    regularExpression = [NSString stringWithFormat:@"project +'%@.", oldString];
    expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [fileContent replaceCharactersInRange:obj.range withString:[NSString stringWithFormat:@"project '%@.", newString]];
    }];
    
    [fileContent writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
}

#pragma mark - 修改ProjectFile
+(void)replaceProjectFileContent:(NSString *)filePath
                       oldString:(NSString *)oldString
                       newString:(NSString *)newString {
    
    NSMutableString *fileContent = [NSMutableString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    
    NSString *regularExpression = [NSString stringWithFormat:@"\\b%@\\b", oldString];
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:regularExpression options:0 error:nil];
    NSArray<NSTextCheckingResult *> *matches = [expression matchesInString:fileContent options:0 range:NSMakeRange(0, fileContent.length)];
    [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [fileContent replaceCharactersInRange:obj.range withString:newString];
    }];
    
    [fileContent writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
}


@end
